package com.scs.application.modules.svn.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.scs.application.core.consts.Const;
import com.scs.application.core.exception.BusinessException;
import com.scs.application.core.utils.FileUtils;
import com.scs.application.core.utils.StringUtils;
import com.scs.application.modules.base.util.CommonService;
import com.scs.application.modules.svn.SVNHelper;
import com.scs.application.modules.svn.dto.SVNLockInfo;
import com.scs.application.modules.svn.dto.SVNOperateDTO;
import com.scs.application.modules.svn.enums.SVNFileLockStatus;
import com.scs.application.modules.svn.service.SVNService;
import com.scs.application.modules.sys.service.impl.DataViewServiceImpl;
import org.springframework.stereotype.Service;

import java.io.File;

/**
 * <p>
 * SVN 服务实现类
 * </p>
 */
@Service
public class SVNServiceImpl implements SVNService {
    File sourceFile;

    @Override
    public void setSourceFile(String sourceType, String fileName) {
        if (sourceType.equalsIgnoreCase("menu")) {
            fileName = Const.MENU_FILE_SRC;
        } else if (sourceType.equalsIgnoreCase("init-data")) {
            fileName = Const.INIT_DATA_SQL_SRC;
        } else if (sourceType.equalsIgnoreCase("init-data-sql")) {
            String fileNameOld = fileName;
            fileName = Const.INIT_DATE_SRC + fileName + ".txt";
            File file = new File(fileName);
            if (!file.exists()) {
                try {
                    file.createNewFile();

                    //将init-data-sql.json 对应的sql存到该文件里面
                    JSONObject sqlStore = JSONObject.parseObject(FileUtils.readFileStore(Const.getInitDataSqlSrc()));
                    JSONArray items = sqlStore.getJSONArray("items");

                    boolean isEdit = false;
                    for (int i = 0; i < items.size(); i++) {
                        JSONObject item = items.getJSONObject(i);
                        String tables = item.getString("tables");
                        String sql = item.getString("sql");
                        if ((tables).equals(fileNameOld)) {
                            if (StringUtils.isNotBlank(sql)) {
                                FileUtils.writeStringToFile(file, sql, "utf-8");
                                items.getJSONObject(i).remove("sql");
                                isEdit = true;
                            }
                            break;
                        }
                    }

                    if (isEdit) {
                        sqlStore.put("items", items);
                        FileUtils.writeTxtFile(Const.INIT_DATA_SQL_SRC, JSON.toJSONString(sqlStore, SerializerFeature.PrettyFormat));
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } else if (sourceType.equalsIgnoreCase("dataview")) {
            fileName = Const.DATA_VIEW_DTL_SRC + fileName + ".json";
        }
        String protocol = Const.class.getClassLoader().getResource("").getProtocol();
        try {
            if (protocol.startsWith("jar")) {
                fileName = fileName.substring(fileName.indexOf("/static/") > -1 ? fileName.indexOf("/static/") : 0);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        this.sourceFile = new File(fileName);
    }

    @Override
    public SVNLockInfo status(SVNOperateDTO para) {
        SVNLockInfo svnLockInfo = null;
        setSourceFile(para.getSourceType(), para.getFileName());
        if ("dataview".equals(para.getSourceType())) {
            if (DataViewServiceImpl.svnLockInfoMap.containsKey(para.getFileName())) {
                svnLockInfo = DataViewServiceImpl.svnLockInfoMap.get(para.getFileName());
            } else {
                svnLockInfo = getSVNStatus();
                DataViewServiceImpl.svnLockInfoMap.put(para.getFileName(), svnLockInfo);
            }
        } else {
            svnLockInfo = getSVNStatus();
        }
        return svnLockInfo;
    }

    private SVNLockInfo getSVNStatus() {
        try {
            return SVNHelper.getLockInfo(sourceFile);
        } catch (Exception e) {
            throw new BusinessException(e.getMessage());
        }
    }

    @Override
    public SVNLockInfo add() {
        try {
            SVNHelper.addFile(sourceFile);
            return SVNHelper.getLockInfo(sourceFile);
        } catch (Exception e) {
            throw new BusinessException("添加资源发生错误：" + e.getMessage());
        }
    }

    @Override
    public SVNLockInfo lock(SVNOperateDTO svnOperateDTO) {
        SVNLockInfo lockInfo;
        try {
            lockInfo = SVNHelper.getLockInfo(sourceFile);
            if (lockInfo.getLockStatus() == SVNFileLockStatus.LOCK || lockInfo.getLockStatus() == SVNFileLockStatus.LOCK_BY_SELF) {
                return lockInfo;
            } else {
                SVNHelper.updateFile(sourceFile);
                SVNHelper.lockFile(sourceFile);
                SVNLockInfo svnLockInfo = SVNHelper.getLockInfo(sourceFile);
                if (svnOperateDTO.getSourceType().equals("dataview")) {
                    DataViewServiceImpl.svnLockInfoMap.remove(svnOperateDTO.getFileName());
                    DataViewServiceImpl.svnLockInfoMap.put(svnOperateDTO.getFileName(), svnLockInfo);
                }
                return svnLockInfo;
            }
        } catch (Exception e) {
            throw new BusinessException("锁定资源发生错误：" + e.getMessage());
        }
    }

    @Override
    public SVNLockInfo commit(SVNOperateDTO svnOperateDTO) {
        SVNLockInfo lockInfo;
        try {
            lockInfo = SVNHelper.getLockInfo(sourceFile);
            if (lockInfo.getLockStatus() == SVNFileLockStatus.FREE) {
                throw new BusinessException("资源已处于未锁定状态，不能提交！");
            } else if (lockInfo.getLockStatus() == SVNFileLockStatus.LOCK) {
                throw new BusinessException("资源被工作站：" + lockInfo.getStation() + "锁定，本工作站不能提交了！");
            } else {
//                Calendar cal = Calendar.getInstance();
//                SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
//                cal.setTimeInMillis(sourceFile.lastModified());
//                String sourceFileLast = formatter.format(cal.getTime());
//                String dateNow = DateUtils.format(DateUtils.now(),"yyyy-MM-dd HH:mm:ss.SSS");
//                if (sourceFileLast.equals(dateNow)) throw new BusinessException("该文件尚未修改过，不需要提交<br>最近修改日期：")

                //文件没有被修改则不需要提交
                // 老是出问题，提交前清除各类日志文件及状态
                SVNHelper.cleanupFile(new File(Const.FILE_STORE_SRC));
                SVNHelper.commitFile(sourceFile, svnOperateDTO.getRemark());
//                if (lockInfo.getLockStatus() == SVNFileLockStatus.LOCK_BY_SELF) {
//                    SVNHelper.unLockFile(sourceFile);
//                }
                SVNLockInfo svnLockInfo = SVNHelper.getLockInfo(sourceFile);
                //如果提交后，状态还是锁定，说明文件尚未修改过
                if (svnLockInfo.getLockStatus().name().equals(SVNFileLockStatus.LOCK_BY_SELF.name()))
                    throw new BusinessException("该文件尚未修改过，不需要提交，请撤销：");
                if (svnOperateDTO.getSourceType().equals("dataview")) {
                    DataViewServiceImpl.svnLockInfoMap.remove(svnOperateDTO.getFileName());
                    DataViewServiceImpl.svnLockInfoMap.put(svnOperateDTO.getFileName(), svnLockInfo);
                    CommonService.cacheDataview(svnOperateDTO.getFileName());
                }
                return svnLockInfo;
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException("提交资源发生错误：" + e.getMessage());
        }
    }

    @Override
    public SVNLockInfo revert(SVNOperateDTO svnOperateDTO) {
        SVNLockInfo lockInfo;
        try {
            lockInfo = SVNHelper.getLockInfo(sourceFile);
            if (lockInfo.getLockStatus() == SVNFileLockStatus.LOCK) {
                throw new BusinessException("资源被工作站：" + lockInfo.getStation() + "锁定，本工作站不能撤销！");
            }

            if (lockInfo.getLockStatus() == SVNFileLockStatus.ADDED) {
                SVNHelper.revertFile(sourceFile);
                return SVNHelper.getLockInfo(sourceFile);
            } else if (lockInfo.getLockStatus() == SVNFileLockStatus.LOCK_BY_SELF) {
                SVNHelper.revertFile(sourceFile);
                SVNHelper.unLockFile(sourceFile);
                SVNLockInfo svnLockInfo = SVNHelper.getLockInfo(sourceFile);
                if (svnOperateDTO.getSourceType().equals("dataview")) {
                    DataViewServiceImpl.svnLockInfoMap.remove(svnOperateDTO.getFileName());
                    DataViewServiceImpl.svnLockInfoMap.put(svnOperateDTO.getFileName(), svnLockInfo);
                    CommonService.cacheDataview(svnOperateDTO.getFileName());
                }
                return svnLockInfo;
            } else {
                throw new BusinessException("资源只有处于自己锁定状态或新增状态时，才能撤销！");
            }
        } catch (Exception e) {
            throw new BusinessException("撤销提交资源发生错误：" + e.getMessage());
        }

    }

    @Override
    public SVNLockInfo delete() {
        SVNLockInfo lockInfo;
        try {
            lockInfo = SVNHelper.getLockInfo(sourceFile);
            if (lockInfo.getLockStatus() == SVNFileLockStatus.FREE) {
                throw new BusinessException("资源已处于未锁定状态，不能删除！");
            } else if (lockInfo.getLockStatus() == SVNFileLockStatus.LOCK) {
                throw new BusinessException("资源被工作站：" + lockInfo.getStation() + "锁定，本工作站不能删除！");
            } else {
                SVNHelper.deleteFile(sourceFile);
                SVNHelper.commitFile(sourceFile);
                return new SVNLockInfo(SVNFileLockStatus.DELETED);
            }
        } catch (Exception e) {
            throw new BusinessException("删除资源发生错误：" + e.getMessage());
        }

    }

    @Override
    public Boolean isSupport(Boolean flagProject) {
        return !flagProject;
    }
}
